import pandas as pd
import numpy as np
import time

params = {
    'a': [0.178, 0.309, 0.431, 0.252, 0.312],
    'b': -0.293,
    'c': -2.160,
    'lambda_': 0.058,
    'd3': 0.078,
    'd5': -0.144,
    'e': -0.127,
    'mu': 1.751,
    'k': 3.492
}

def parse_schedule(df):
    section_counts = [0] * 5
    days_with_class = 0
    early_count = 0
    afternoon_count = 0
    consecutive_pairs = 0
    total_classes = 0
    has_lunch_break = True
    free_day_count = 0
    all_days_have_morning = True

    for day in ['周一', '周二', '周三', '周四', '周五']:
        daily = df[day].fillna('')
        class_indices = [i for i, val in enumerate(daily[:5]) if val == '有课']
        if not class_indices:
            free_day_count += 1
        else:
            days_with_class += 1
            if 2 in class_indices:
                if 1 in class_indices:
                    has_lunch_break = False
            if 0 not in class_indices:
                all_days_have_morning = False

        for i in class_indices:
            section_counts[i] += 1
            total_classes += 1
            if i == 0:
                early_count += 1
            if i >= 2:
                afternoon_count += 1
        consecutive_pairs += sum([1 for i in range(4) if i in class_indices and i+1 in class_indices])

    I3 = 1 if days_with_class == 3 else 0
    I5 = 1 if days_with_class == 5 else 0

    return section_counts, early_count, afternoon_count, consecutive_pairs, I3, I5, total_classes, has_lunch_break, free_day_count, all_days_have_morning, days_with_class

def compute_score(section_counts, early, afternoon, consecutive, I3, I5, p):
    score = 0
    for j in range(5):
        score += p['a'][j] * np.log(1 + section_counts[j])
    score += p['b'] * (np.log(1 + afternoon) - np.log(1 + section_counts[0] + section_counts[1]))
    score += p['c'] * (1 - np.exp(-p['lambda_'] * consecutive))
    score += p['d3'] * I3 + p['d5'] * I5
    score += p['e'] * (1 - np.exp(-p['mu'] * early))
    score *= p['k']
    return score

def adjust_score_by_total_classes(score, total):
    base = score / 5 * 100
    if total == 1:
        return 100.0
    elif total == 2:
        return 98.5
    elif total <= 5:
        return max(base, 95.0)
    elif total <= 8:
        return max(base, 85.0)
    elif total < 12:
        factor = 1 + (12 - total) * 0.02
        return min(100.0, base * factor)
    elif total == 12:
        return base
    elif total > 20 and total < 25:
        penalty = (total - 20) * 12
        return max(0.0, base - penalty)
    elif total >= 25:
        return 0.0
    else:
        factor = 1 - (total - 12) * 0.03
        return max(0.0, base * factor)

def generate_comment(score, section_counts, early_count, consecutive_pairs, I5, has_lunch_break, total_classes, free_day_count, all_days_have_morning, days_with_class):
    pros, cons = [], []

    if early_count == 0:
        pros.append("课表没有早八，符合大多数学生作息。")
    elif early_count <= 2:
        pros.append("早八安排较少，影响较小。")
    else:
        cons.append("早八课程较多，建议适当减少。")

    if consecutive_pairs >= 4:
        pros.append("连课安排合理，时间利用效率高。")
    elif consecutive_pairs <= 2:
        cons.append("课程分布较散，建议适当连课以减少等待。")

    if I5 == 0 and total_classes <= 20:
        pros.append("不是五天上课，有整块空闲时间，利于休息。")
    elif total_classes <= 20:
        cons.append("一周五天都有课，建议尝试集中排课至四天。")

    if has_lunch_break:
        pros.append("课程安排保留了午休时间，有利于恢复精力。")
    else:
        cons.append("存在午休时间被占用，易造成疲劳。")

    if total_classes <= 10:
        pros.append("课程总量适中，压力不大。")
    elif total_classes >= 16:
        cons.append("课程总量偏多，可能影响休息。")

    if free_day_count >= 1:
        pros.append("存在整天无课，可合理安排自习或活动。")

    if not all_days_have_morning:
        pros.append("有些天无早课，节奏更舒缓。")

    print(f"该课表的满意度评分为：{score} 分（百分制）\n")
    if score >= 95:
        print("评价：此课表结构合理。")
        for p in pros[:3]:
            print(f"- 优点：{p}")
    elif score >= 85:
        print("评价：此课表较为合理。")
        for p in pros[:3]:
            print(f"- 优点：{p}")
        if cons:
            print(f"- 缺点：{cons[0]}")
    elif score >= 60:
        print("评价：此课表有改进空间，建议如下：")
        for p in pros[:2]:
            print(f"- 优点：{p}")
        for c in cons[:2]:
            print(f"- 缺点：{c}")
    else:
        print("评价：此课表安排不合理，建议进行优化调整：")
        for c in cons[:4]:
            print(f"- 缺点：{c}")

def main():
    file_path = "course.xlsx"
    df = pd.read_excel(file_path)

    section_counts, early_count, afternoon_count, consecutive_pairs, I3, I5, total_classes, has_lunch_break, free_day_count, all_days_have_morning, days_with_class = parse_schedule(df)
    raw_score = compute_score(section_counts, early_count, afternoon_count, consecutive_pairs, I3, I5, params)
    percent_score = round(adjust_score_by_total_classes(raw_score, total_classes), 2)
    generate_comment(percent_score, section_counts, early_count, consecutive_pairs, I5, has_lunch_break, total_classes, free_day_count, all_days_have_morning, days_with_class)

    print(" ")
    time.sleep(30)

if __name__ == "__main__":
    main()
